package com.kmzx.one.project.service.impl;

import com.google.gson.Gson;
import com.kmzx.one.common.exceptions.NoSuchObjectException;
import com.kmzx.one.common.utils.StringUtils;
import com.kmzx.one.common.utils.UUIDGenerator;
import com.kmzx.one.project.config.data.QiNiuConfig;
import com.kmzx.one.project.config.data.WXDataConfig;
import com.kmzx.one.project.entity.UserAuthentication;
import com.kmzx.one.project.entity.UserInvite;
import com.kmzx.one.project.entity.UserProfit;
import com.kmzx.one.project.entity.UserRank;
import com.kmzx.one.project.entity.UserShareMini;
import com.kmzx.one.project.entity.UserSharePics;
import com.kmzx.one.project.entity.WxUser;
import com.kmzx.one.project.events.ShareMiniEvent;
import com.kmzx.one.project.mapper.CustomerMapper;
import com.kmzx.one.project.mapper.UserAuthenticationMapper;
import com.kmzx.one.project.mapper.UserInviteMapper;
import com.kmzx.one.project.mapper.UserProfitMapper;
import com.kmzx.one.project.mapper.UserRankMapper;
import com.kmzx.one.project.mapper.WxUserMapper;
import com.kmzx.one.project.others.dso.OrderBeSendDso;
import com.kmzx.one.project.others.dso.RankUserDso;
import com.kmzx.one.project.others.dso.UserFansDso;
import com.kmzx.one.project.others.dso.UserRankDso;
import com.kmzx.one.project.others.dto.UserAuthInfo;
import com.kmzx.one.project.others.dto.UserCenterInfo;
import com.kmzx.one.project.others.dto.UserProfitInfo;
import com.kmzx.one.project.others.wxo.MySelfCodeUnLimit;
import com.kmzx.one.project.service.UserCenterService;
import com.qiniu.common.QiniuException;
import com.qiniu.common.Zone;
import com.qiniu.http.Response;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.util.Auth;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import weixin.popular.api.TokenAPI;
import weixin.popular.api.WxaAPI;
import weixin.popular.bean.token.Token;
import weixin.popular.bean.wxa.LineColor;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Service
public class UserCenterServiceImpl implements UserCenterService {

    @Autowired
    private WxUserMapper wxUserMapper;

    @Autowired
    private UserRankMapper userRankMapper;

    @Autowired
    private UserProfitMapper userProfitMapper;

    @Autowired
    private UserInviteMapper userInviteMapper;

    @Autowired
    private CustomerMapper customerMapper;

    @Autowired
    UserAuthenticationMapper userAuthenticationMapper;

    @Autowired
    private RedisTemplate<String, Object> stringObjectRedisTemplate;

    // 数据配置
    @Autowired
    private QiNiuConfig qiNiuConfig;

    @Autowired
    private WXDataConfig wxConfig;


    @Override
    public WxUser findByOpenId(String openId) throws Exception {
        WxUser wxUser = wxUserMapper.selectByOpenId(openId);
        return wxUser;
    }

    @Override
    public WxUser doInsertWxUser(WxUser wxUser, String parent) throws Exception {
        String s = UUIDGenerator.generate();
        Date date = new Date();
        List<RankUserDso> userDtoList = wxUserMapper.selectUserRankTabNo();
        if (!CollectionUtils.isEmpty(userDtoList)) {
            userDtoList.sort(Comparator.comparing(RankUserDso::getRankNum));
            String rankId = userDtoList.get(0).getRankId();
            UserRank userRank = new UserRank();
            userRank.setUserId(s);
            userRank.setCreateTime(date);
            userRank.setDeleted(0);
            userRank.setId(UUIDGenerator.generate());
            userRank.setMyGrowthValue(0.0);
            userRank.setRankId(rankId);

            UserProfit profit = new UserProfit();
            profit.setId(UUIDGenerator.generate());
            profit.setUserId(s);
            profit.setCreateTime(date);
            profit.setDeleted(0);
            profit.setProfitMoney(BigDecimal.ZERO);
            profit.setAccountMoney(BigDecimal.ZERO);
            profit.setStates(0);
            profit.setUpdateTime(date);

            userRankMapper.insert(userRank);
            userProfitMapper.insert(profit);

            logger.info("-----------初始化用户的资金账户:{},以及等级账户:{}", profit, userRank);
        }


        wxUser.setId(s);
        wxUser.setCreateTime(date);
        wxUser.setUpdateTime(date);
        wxUser.setDeleted(0);
        wxUser.setStates(0);

        if (StringUtils.isNotEmpty(parent)) {
            UserInvite userInvite = new UserInvite();
            userInvite.setId(UUIDGenerator.generate());
            userInvite.setCreateTime(date);
            userInvite.setUpdateTime(date);
            userInvite.setFromUser(parent);
            userInvite.setToUser(s);
            userInvite.setStates(0);
            userInviteMapper.insert(userInvite);
            logger.info("-----------初始化用户的邀请人:{}", userInvite);
        }else {
            // 初始化为官方号
            UserInvite userInvite = new UserInvite();
            userInvite.setId(UUIDGenerator.generate());
            userInvite.setCreateTime(date);
            userInvite.setUpdateTime(date);
            userInvite.setFromUser("5f60324fd964428782e187751da3e190");
            userInvite.setToUser(s);
            userInvite.setStates(0);
            userInviteMapper.insert(userInvite);
        }
        wxUserMapper.insertWxUser(wxUser);
        logger.info("-----------初始化用户账号:{}", wxUser);
        return wxUser;
    }

    @Override
    public Integer doUpdateWxUser(WxUser wxUser) throws Exception {
        Integer result = wxUserMapper.doUpdateWxUser(wxUser);
        return result;
    }

    @Override
    public UserCenterInfo findUserTopInfo(String userId) throws Exception {
        UserCenterInfo userInfo = wxUserMapper.selectUserTopInfo(userId);
        if (userInfo != null) {
            Integer rankNum = userInfo.getRankNum();
            userInfo.setOneFans(0);
            userInfo.setAllFans(0);
            userInfo.setTotalIncome(BigDecimal.ZERO);
            Double seaRankRate = userInfo.getSeaRankRate();
            if (seaRankRate == null) {
                userInfo.setSeaRankRate(1.0);
            }
            if (rankNum != 0) {
                List<UserFansDso> fans = wxUserMapper.selectUserL1Fans(userId);
                if (!CollectionUtils.isEmpty(fans)) {
                    userInfo.setOneFans(fans.size());
                    if (rankNum == 1) {
                        userInfo.setAllFans(fans.size());
                    }

                    if (rankNum == 2) {
                        List<String> collect = fans.stream().filter(fs -> fs.getLevels() == 1).map(fss -> fss.getUserId()).collect(Collectors.toList());
                        if (!CollectionUtils.isEmpty(collect)) {
                            List<UserFansDso> allFans = wxUserMapper.selectUserAllFans(collect);
                            userInfo.setAllFans(allFans.size() + fans.size());
                        } else {
                            userInfo.setAllFans(fans.size());
                        }

                    }

                    if (rankNum == 3) {
                        List<String> collect = fans.stream().filter(fs -> fs.getLevels() == 2).map(fss -> fss.getUserId()).collect(Collectors.toList());
                        if (!CollectionUtils.isEmpty(collect)) {
                            List<UserFansDso> allFans = wxUserMapper.selectUserAllFans(collect);
                            userInfo.setAllFans(allFans.size() + fans.size());
                        } else {
                            userInfo.setAllFans(fans.size());
                        }

                        List<String> collect1 = fans.stream().filter(fs -> fs.getLevels() == 1).map(fss -> fss.getUserId()).collect(Collectors.toList());
                        if (!CollectionUtils.isEmpty(collect1)) {
                            List<UserFansDso> allFans = wxUserMapper.selectUserAllFans(collect1);
                            int allFans1 = userInfo.getAllFans();
                            userInfo.setAllFans(allFans.size() + allFans1);
                        }
                    }
                }
                userInfo.setTotalIncome(getUserProfit(userId));
            }
            List<UserRankDso> tabs = userRankMapper.selectAllRankTabs();
            for (int i = 0; i < tabs.size(); i++) {
                if (tabs.get(i).getRankId().equals(userInfo.getRankId()) && i != tabs.size() - 1) {
                    userInfo.setNextName(tabs.get(i + 1).getRankName());
                    userInfo.setNextMoney(tabs.get(i + 1).getRankPay());
                    break;
                }
            }
        }
        List<OrderBeSendDso> userTwoInfo = wxUserMapper.selectUserTwoInfo(userId);

        if (!CollectionUtils.isEmpty(userTwoInfo)&& userTwoInfo.size() > 0) {
            for (OrderBeSendDso beSendDto : userTwoInfo) {
                Integer states = beSendDto.getStates();
                if (states == 0) {
                    userInfo.setBePaid(beSendDto.getNumbers());
                }
                if (states == 2) {
                    userInfo.setBeAccepted(beSendDto.getNumbers());
                }
                if (states == 1) {
                    userInfo.setBeSend(beSendDto.getNumbers());
                }
            }
        }
        int i = wxUserMapper.countOldFans(userId);
        userInfo.setBeforeFans(i);
        return userInfo;
    }

    @Override
    public UserCenterInfo findUserTwoInfo(String userId) throws Exception {
        List<OrderBeSendDso> userTwoInfo = wxUserMapper.selectUserTwoInfo(userId);
        if (!CollectionUtils.isEmpty(userTwoInfo) && userTwoInfo.size() > 0) {
            UserCenterInfo dto = new UserCenterInfo();
            for (OrderBeSendDso beSendDto : userTwoInfo) {
                Integer states = beSendDto.getStates();
                if (states == 0) {
                    dto.setBePaid(beSendDto.getNumbers());
                }
                if (states == 1) {
                    dto.setBeSend(beSendDto.getNumbers());
                }
                if (states == 2) {
                    dto.setBeAccepted(beSendDto.getNumbers());
                }
            }
            return dto;
        } else {
            throw new NoSuchObjectException(201,"暂无数据");
        }
    }

    @Override
    public Integer doHasFather(String userId) throws Exception {
        UserCenterInfo userInfo = wxUserMapper.selectUserTopInfo(userId);
        Integer rankNum = userInfo.getRankNum();
        if (rankNum == 0) {
            int count = wxUserMapper.hasTop(userId);
            if (count == 0) {
                // 1 代表没有邀请人
                // 0 代表  有邀请人
                return 1;
            }
        }
        return 0;
    }

    @Override
    public UserAuthInfo doCheckUserAuth(String userId) throws Exception {
        List<UserAuthInfo> infos = customerMapper.checkUserAuth(userId);

        if (CollectionUtils.isEmpty(infos)) {
            UserAuthInfo info = new UserAuthInfo();
            // 1 代表没有认证
            info.setHas(1);
            return info;
        } else {
            UserAuthInfo userAuthInfo = infos.get(0);
            String idCard = userAuthInfo.getIdCard();
//            idCard.su
            UserProfitInfo profit = customerMapper.selectUserProfit(userId);
            if (profit != null) {
                userAuthInfo.setMoney(profit.getTotalAmount());
            }
            userAuthInfo.setHas(0);
            return userAuthInfo;
        }
    }

    @Override
    public UserAuthInfo doUserAuth(String userId, String name, String idCard) throws Exception {
        List<UserAuthInfo> infos = customerMapper.checkUserAuth(userId);

        if (CollectionUtils.isEmpty(infos)) {
            UserAuthentication auth = new UserAuthentication();
            auth.setId(UUIDGenerator.generate());
            auth.setUserId(userId);
            auth.setCreateTime(new Date());
            auth.setUserName(name);
            auth.setIdCard(idCard);
            auth.setStates(0);
            auth.setDeleted(0);
            auth.setUpdateTime(auth.getCreateTime());
            userAuthenticationMapper.insert(auth);

            UserAuthInfo info = new UserAuthInfo();
            info.setIdCard(idCard).setName(name).setHas(0);
            UserProfitInfo profit = customerMapper.selectUserProfit(userId);
            if (profit != null) {
                info.setMoney(profit.getTotalAmount());
            }
            return info;
        } else {
            UserAuthInfo info = infos.get(0);
            info.setIdCard(idCard).setName(name);
            String temp = info.getTemp();
            int i = userAuthenticationMapper.updateUserAuth(temp, name, idCard, new Date());
            info.setTemp(null);
            UserProfitInfo profit = customerMapper.selectUserProfit(userId);
            if (profit != null) {
                info.setMoney(profit.getTotalAmount());
            }
            return info;
        }
    }

    @Autowired
    ApplicationContext applicationContext;

    @Override
    public String findUserShareMini(String userId) throws Exception{

        WxUser wxUser = wxUserMapper.selectById(userId);
        if(wxUser==null){
            throw new NoSuchObjectException("该用户不存在");
        }

        UserShareMini userShareMini = customerMapper.selectUserShareMiniCode(userId);
        if(userShareMini!=null){
            String miniUrl = userShareMini.getMiniUrl();
            applicationContext.publishEvent(new ShareMiniEvent(2,userShareMini));
            return miniUrl;
        }

        MySelfCodeUnLimit getwxacodeunlimit = new MySelfCodeUnLimit();

        getwxacodeunlimit.setAuto_color(true);
        getwxacodeunlimit.setScene(userId);
        getwxacodeunlimit.setWidth(430);
        getwxacodeunlimit.setPage("pages/list/list");
        LineColor lineColor = new LineColor();
        lineColor.setR("");
        lineColor.setG("");
        lineColor.setB("");
        getwxacodeunlimit.setIs_hyaline(true);
        getwxacodeunlimit.setLine_color(lineColor);

        BufferedImage bufferedImage = WxaAPI.getwxacodeunlimit(getRightAccessToken(), getwxacodeunlimit);

        String sendImg = "";

        logger.info("bufferedImage.toString() = " + bufferedImage.toString());


        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ImageOutputStream imageOutput = ImageIO.createImageOutputStream(byteArrayOutputStream);
        ImageIO.write(bufferedImage, "png", imageOutput);
        InputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
        String png = generateFileName("png");
        String fullPath = "kmzx/share/user/" + png;
        asyncUpload(fullPath, byteArrayInputStream);
        String sendPath = qiNiuConfig.getDomainHost() + fullPath;
        sendImg = sendPath;

        Date now = new Date();
        UserShareMini shareMini = new UserShareMini();
        shareMini.setId(UUIDGenerator.generate());
        shareMini.setCreateTime(now);
        shareMini.setDeleted(0);
        shareMini.setUserId(userId);
        shareMini.setKinds(1);
        shareMini.setMiniUrl(sendImg);

        applicationContext.publishEvent(new ShareMiniEvent(1,shareMini));
        return sendImg;
    }

    @Override
    public List<String> findSpecificUser() {

        return null;
    }

    public BigDecimal getUserProfit(String userId) {
        List<UserProfit> userProfits = userProfitMapper.selectByUserId(userId);
        if (!CollectionUtils.isEmpty(userProfits)) {
            BigDecimal profitMoney = userProfits.get(0).getAccountMoney();
            return profitMoney;
        }
        return BigDecimal.ZERO;
    }

    /**
     * 异步上传数据
     *
     * @param fileName
     * @param input
     */
    public void asyncUpload(String fileName, InputStream input) {
        Configuration cfg = new Configuration(Zone.huanan());
        UploadManager uploadManager = new UploadManager(cfg);
        String accessKey = qiNiuConfig.getAppKey();
        String secretKey = qiNiuConfig.getAppSecret();
        String bucket = qiNiuConfig.getBucketName1();
        Auth auth = Auth.create(accessKey, secretKey);
        String upToken = auth.uploadToken(bucket);
        try {
            Response response = uploadManager.put(input, fileName, upToken, null, null);
            //解析上传成功的结果
            DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
            logger.info("请求返回的数据key:{}", putRet.key);
            logger.info("请求返回的数据Hash:{}", putRet.hash);
        } catch (QiniuException ex) {
            Response r = ex.response;
            System.err.println(r.toString());
            try {
                System.err.println(r.bodyString());
            } catch (QiniuException ex2) {
            }
        }
    }

    public String getRightAccessToken() {
        Object obj = stringObjectRedisTemplate.opsForValue().get("messageToken");
        String wxTokens = null;
        if (obj != null) {
            String mt = (String) obj;
            wxTokens = mt;
        } else {
            Token token = TokenAPI.token(wxConfig.getAppId(), wxConfig.getAppSecret());
            String access_token = token.getAccess_token();
            int secend = token.getExpires_in();
            wxTokens = access_token;
            stringObjectRedisTemplate.opsForValue().set("messageToken", access_token, 7100, TimeUnit.SECONDS);
        }
        return wxTokens;
    }


    @Autowired
    private AtomicInteger atomicInteger;

    public String generateFileName(String fileType) {
        Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR);
        StringBuilder sb = new StringBuilder();
        sb.append(year);
        sb.append("/");
        sb.append(calendar.get(Calendar.MONTH) + 1);
        sb.append("/");
        sb.append(calendar.get(Calendar.DAY_OF_MONTH));
        sb.append("-");
        sb.append(calendar.get(Calendar.HOUR_OF_DAY));// 1位
        sb.append(calendar.get(Calendar.MINUTE));// 1位
        sb.append(calendar.get(Calendar.SECOND));// 1位
        sb.append("-");
        sb.append(atomicInteger.getAndIncrement());
        sb.append(RandomStringUtils.randomAlphanumeric(6));
        sb.append(".");
        sb.append(fileType);
        return sb.toString();
    }
}
